<?php
/**
 * Created by PhpStorm.
 * User: sunzexin
 * Date: 2017/12/21
 * Time: 13:45
 */

namespace App\Http\Logics;
use App\Http\Logics\MiniProgram\PartnerLogic;
use App\Partner;
use Illuminate\Support\Facades\Redis;
use App\Users;
use Intervention\Image\Facades\Image;
use SimpleSoftwareIO\QrCode\Facades\QrCode;

class BaseLogic
{
    const SUCCESS = 0;

    // 系统错误
    const SYSTEM_ERROR = 1111;
    // 登录失败
    const LOGIN_ERROR = 4001;
    // 用户不存在
    const ACCOUNT_OR_PASSWORD_IS_WRONG = 4002;
    // 用户未登录
    const ACCOUNT_NOT_LOGIN = 4003;
    // 用户注册失败
    const ACCOUNT_REGIST_FAILD = 4004;
    //对象保存失败
    const OBJECT_SAVE_FAIL = 2001;

    // 对象删除失败
    const OBJECT_DELETE_FAILD = 2002;


    // 获取citycode失败
    const GET_CITYCODE_FAILD = 3000;


    // 数据是空的
    const CONTENT_IS_EMPTY = 1000;


    // 用户添加对咖啡馆喜欢失败
    const USER_FOLLOW_CAFE_FAILD = 5000;
    // 用户重复关注咖啡馆
    const USER_FOLLOW_CAFE_AGAIN = 5001;

    // 用户添加对咖啡馆喜欢失败
    const USER_FOLLOW_CITY_FAILD = 5002;
    // 用户重复关注咖啡馆
    const USER_FOLLOW_CITY_AGAIN = 5003;

    // 用户添加对咖啡馆喜欢失败
    const USER_FOLLOW_MARK_FAILD = 5004;
    // 用户重复关注咖啡馆
    const USER_FOLLOW_MARK_AGAIN = 5005;

    // 重复审核
    const SET_CAFE_PASS_AGAIN = 5006;

    // 用户点赞动态失败
    const USER_PRAISE_DYNAMIC_FAILD = 5007;
    // 用户重复点赞动态
    const USER_PRAISE_DYNAMIC_AGAIN = 5008;

    // 通知短信发送失败
    const SMS_SEND_FAILD = 6000;

    // 验证码过期
    const CAPTCHA_IS_EXPIRE = 6001;
    // 验证码错误
    const CAPTCHA_IS_WRONG = 6002;
    // 创建普通二维码失败
    const CREATE_NORMAL_QRCODE_FAILD = 6500;
    // 保存用户二维码失败
    const SAVE_USER_QRCODE_FAILD = 6510;

    // 系统通知发送失败
    const SYSTEM_NOTIFY_SEND_FAILD = 7000;

    // 重复报名
    const PARTY_SIGN_UP_AGAIN = 8000;

    // 重复购买会员卡
    const BUY_VIP_AGAIN = 8100;
    // 购买过其他会员卡
    const BUY_OTHER_VIP = 8101;

    // 重复接受管理员权限
    const GET_MANAGER_AGAIN = 8200;

    // 重复领取代金券
    const GET_CASH_COUPON_AGAIN = 8300;

    // 代金券已经领取完了
    const CASH_COUPON_IS_EMPTY = 8301;

    // 代金券已经过期了
    const CASH_COUPON_IS_EXPIRED = 8302;

    // 重复核销代金券
    const DESTROY_CASH_COUPON_AGAIN = 8400;

    // 支付失败
    const PAY_FAILD = 9000;
    // 支付失败
    const PAY_AGAIN = 9001;
    // 物流查询失败
    const WLXX_FAILD = 9100;


    protected static $errorArray = [
        self::SUCCESS => '成功',
        self::LOGIN_ERROR => '登录错误',
        self::ACCOUNT_OR_PASSWORD_IS_WRONG => '账户或密码错误',
        self::ACCOUNT_NOT_LOGIN => '用户未登录',
        self::OBJECT_SAVE_FAIL => '对象保存失败',
        self::ACCOUNT_REGIST_FAILD => '用户注册失败',
        self::USER_FOLLOW_CAFE_FAILD => '关注咖啡馆失败',
        self::USER_FOLLOW_CITY_FAILD => '关注城市失败',
        self::USER_FOLLOW_MARK_FAILD => '关注标签失败',
        self::GET_CITYCODE_FAILD => '获取citycode失败',
        self::CONTENT_IS_EMPTY => '数据是空的',
        self::USER_FOLLOW_CAFE_AGAIN => '重复关注咖啡馆',
        self::USER_FOLLOW_CITY_AGAIN => '重复关注城市',
        self::USER_FOLLOW_MARK_AGAIN => '重复关注标签',
        self::OBJECT_DELETE_FAILD => '对象删除失败',
        self::SMS_SEND_FAILD  => '通知短信发送失败',
        self::CAPTCHA_IS_EXPIRE => '验证码已过期',
        self::CAPTCHA_IS_WRONG => '验证码错误',
        self::SYSTEM_NOTIFY_SEND_FAILD => '系统通知发送失败',
        self::PARTY_SIGN_UP_AGAIN => '重复报名',
        self::BUY_VIP_AGAIN => '重复购买该会员卡',
        self::BUY_OTHER_VIP => '您已购买其他会员卡',
        self::CREATE_NORMAL_QRCODE_FAILD => '创建普通二维码失败',
        self::SAVE_USER_QRCODE_FAILD => '保存用户二维码失败',
        self::GET_MANAGER_AGAIN => '重复接受管理员权限',
        self::GET_CASH_COUPON_AGAIN => '重复领取代金券',
        self::CASH_COUPON_IS_EMPTY => '代金券已经领取完了',
        self::CASH_COUPON_IS_EXPIRED => '代金券已经过期了',
        self::SYSTEM_ERROR => '系统错误',
        self::DESTROY_CASH_COUPON_AGAIN => '重复核销代金券',
        self::SET_CAFE_PASS_AGAIN => '重复审核咖啡馆',
        self::USER_PRAISE_DYNAMIC_FAILD => '点赞动态失败',
        self::USER_PRAISE_DYNAMIC_AGAIN => '重复点赞动态',
        self::PAY_FAILD => '支付失败',
        self::PAY_AGAIN => '重复支付',
        self::WLXX_FAILD => '物流查询失败'
    ];

    /**
     * @param array $data 需返回的参数
     */
    public static function response($code, $data = [])
    {
        $response = json_encode(array(
            'code' => $code,
            'message' => self::$errorArray[$code],
            'data' => $data
        ));
        return json_decode($response);
    }

    /**
     * curl请求接口函数
     * @param $url
     * @return mixed
     */
    public static function httpGet($url, $headers = []) {
        try {
            $curl = curl_init();
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($curl, CURLOPT_TIMEOUT, 500);
            // 为保证第三方服务器与微信服务器之间数据传输的安全性，所有微信接口采用https方式调用，必须使用下面2行代码打开ssl安全校验。
            // 如果在部署过程中代码在此处验证失败，请到 http://curl.haxx.se/ca/cacert.pem 下载新的证书判别文件。
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
            curl_setopt($curl, CURLOPT_URL, $url);

            $res = curl_exec($curl);
            curl_close($curl);

            return self::response(self::SUCCESS, $res);
        }catch (\Exception $e){
            return self::response(self::SYSTEM_ERROR);
        }
    }

    /**
     * 生成二维码
     * @param $path 要生成二维码的URL
     * @param string $logo 二维码中间LOGO
     * @return string 返回
     */
    public static function createMiniProgressQrcode($loginSession , $path, $logo = '')
    {
        try {
            $response = self::getAccessTokenByLoginSession($loginSession);
            if ($response->code) {
                return self::response($response->code);
            }
            $access_token = $response->data;

            // 拼接处获取小程序二维码的地址
            $create_qrcode_url = 'https://api.weixin.qq.com/wxa/getwxacode?access_token='.$access_token;
            // 请求参数
            $data = [
                "path" => $path,
                'width' => 430
            ];
            $data_string = json_encode($data);
            // 将二维码下载到服务器本地
            $url = downloadImage($create_qrcode_url, $data_string);
            // 将生产的小程序二维码上传到云存储
            $new_url = uploadImage($url, 'qrcode');
            // 将二维码从服务器本地删除
            removeImage($url);

            return self::response(self::SUCCESS, $new_url);
        }catch (\Exception $e){
            return self::response(self::SYSTEM_ERROR);
        }
    }

    /**
     * 生成不限制数量的小程序码
     * @param $page 要生成二维码的小程序页面
     * @param $scene 小程序吗参数
     * @param string $logo 二维码中间LOGO
     * @return string 返回
     */
    public static function createMiniProgressQrcodeUnlimit($partner_id , $page, $scene, $logo = '')
    {
        try {
            $response = self::getAccessTokenByLoginSession($partner_id);
            if ($response->code) {
                return self::response($response->code);
            }
            $access_token = $response->data;

            // 拼接处获取小程序二维码的地址
            $create_qrcode_url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token='.$access_token;
            // 请求参数
            $data = [
                'scene' => $scene,
                'page' => $page,
                'width' => 430
            ];
            $data_string = json_encode($data);
            // 将二维码下载到服务器本地
            $url = downloadImage($create_qrcode_url, $data_string);

            // 判断是否添加中心logo
            if (!empty($logo)) {
                $img = Image::make($url);
                // 将二维码从服务器本地删除
                removeImage($url);
                $new_logo = downloadImage($logo.'?imageMogr2/auto-orient/thumbnail/180x180!');
                $circle_new_logo = getCicleImg($new_logo);
                $img->insert($circle_new_logo, 'top-left', 125, 125);
                removeImage($new_logo);
                removeImage($circle_new_logo);
                $img->save('/temp/cafe-qrcode.jpg', 60);
                $new_url = uploadImage('/temp/cafe-qrcode.jpg', 'qrcode');
                // 将图片从本地服务器删除
                removeImage('/temp/cafe-qrcode.jpg');
            }else{
                // 将生产的小程序二维码上传到云存储
                $new_url = uploadImage($url, 'qrcode');
                // 将二维码从服务器本地删除
                removeImage($url);
            }

            return self::response(self::SUCCESS, $new_url);
        }catch (\Exception $e){
            return self::response(self::SYSTEM_ERROR);
        }
    }

    /**
     * 返回accessToken
     * @return mixed 返回accessToken
     */
    public static function getAccessTokenByLoginSession($partner_id){
        try {
            // 先尝试从Redis缓存中读取access_token
            $access_token = Redis::get($partner_id.'_access_token');
            // 首先判断token是否过期
            if (empty($access_token)) {
                // 判断是一间咖啡馆小程序登录还是合作者小程序登录

                $response = PartnerLogic::getAppidByPartnerId($partner_id);
                if ($response->code) {
                    return self::response(self::CONTENT_IS_EMPTY);
                }
                $partner = $response->data;
                // 如果是合作者小程序登录，则从数据库中读取小程序的配置
                $access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $partner->appid . "&secret=" . $partner->secret;
                $res = dealHttp($access_token_url);
                $access_token = $res->access_token;
                // 给token赋值，并设置token生存时间3600秒
                Redis::set($partner_id.'access_token', $access_token);
                Redis::expire($partner_id.'access_token', 3600);
            }
            return self::response(self::SUCCESS, $access_token);
        }catch (\Exception $e){
            return self::response(self::SYSTEM_ERROR);
        }
    }

    /**
     * 根据坐标返回地点数据
     * @param $latlng 坐标
     * @return mixed 地点数据
     */
    public static function getAddr($latlng)
    {
        try {
            $homepage = file_get_contents('http://restapi.amap.com/v3/geocode/regeo?output=JSON&location=' . $latlng . '&key=291f9ad46a4ab46cc442157ca8b573c8&radius=1000&extensions=all');
            $homepage = json_decode(($homepage));
            $regeocodes = $homepage->regeocode;         //逆地理编码列表
            $address_component = $regeocodes->addressComponent;

            return self::response(self::SUCCESS, $address_component);
        }catch (\Exception $e){
            return self::response(self::SYSTEM_ERROR);
        }
    }

    /**
     * 发送短信
     * @param $mobile 手机号
     * @param $content 短信内容
     */
    public static function sendSms($data)
    {
        try {
            $apikey = config('app.yunpian_sms.appkey'); //请用自己的apikey代替
            $text = $data['sign'];
            $text .= $data['content'];
            $ch = curl_init();
            $data = array('text' => $text, 'apikey' => $apikey, 'mobile' => $data['mobile']);
            curl_setopt($ch, CURLOPT_URL, 'https://sms.yunpian.com/v2/sms/batch_send.json');
            curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            $json_data = curl_exec($ch);
            //解析返回结果（json格式字符串）
            $array = json_decode($json_data, true);
            return self::response(self::SUCCESS, $array);
        }catch (\Exception $e){
            return self::response(self::SYSTEM_ERROR);
        }
    }

    /**
     * 中文转拼音
     * @param $string 字符串
     * @return mixed 拼音
     */
    public function chineseToPinyin($string){
        try {
            $pinyin = app('pinyin');
            $string = $pinyin->sentence($string);
            return self::response(self::SUCCESS, $string);
        }catch (\Exception $e){
            return self::response(self::SYSTEM_ERROR);
        }
    }

    /**
     * 返回用户信息
     * @param string $openid 用户的wx_app_open_id
     * @return mixed 返回用户信息
     */
    public static function getUserByOpenid($openid = '')
    {
        try {
            $user = Users::where('wx_app_openid', $openid)->first();
            if (!$user) {
                return self::response(self::ACCOUNT_OR_PASSWORD_IS_WRONG);
            }
            return self::response(self::SUCCESS, $user);
        }catch (\Exception $e){
            return self::response(self::SYSTEM_ERROR);
        }
    }

    /**
     * 通过经纬度获取到城市的citycode
     * @param $latlng 经纬度
     * @return mixed 城市的citycode
     */
    public static function getCitycodeByGps($latlng)
    {
        try {
            $homepage = file_get_contents('http://restapi.amap.com/v3/geocode/regeo?output=JSON&location=' . $latlng . '&key=291f9ad46a4ab46cc442157ca8b573c8&radius=1000&extensions=all');
            $homepage = json_decode(($homepage));
            // 逆地理编码列表
            $regeocodes = $homepage->regeocode;
            $addressComponent = $regeocodes->addressComponent;
            if (!$addressComponent) {
                // 获取城市信息失败
                return self::response(self::GET_CITYCODE_FAILD);
            }
            return self::response(self::SUCCESS, $addressComponent->citycode);
        }catch (\Exception $e){
            return self::response(self::SYSTEM_ERROR);
        }
    }

    /**
     * 通过loginSession返回合作者ID
     * @param $loginSession
     * @return mixed 合作者ID
     */
    public static function getPartnerIdByLoginSession($loginSession){
        try {
            $wx_app_openid = Redis::get($loginSession);
            $user = Users::where('wx_app_openid', $wx_app_openid)->first();
            if (empty($user)) {
                return self::response(self::CONTENT_IS_EMPTY);
            }
            return self::response(self::SUCCESS, $user->partner_id);
        }catch (\Exception $e){
            return self::response(self::SYSTEM_ERROR);
        }
    }

    /**
     * 通过商户的loginSession获取商户的user_id,再通过user_id获取partner_id
     * @param $loginSession
     */
    public static function getPartnerId($loginSession)
    {
        try {
            $response = self::getUserIdByLoginSession($loginSession);
            if ($response->code) {
                return self::response($response->code);
            }
            $user_id = $response->data;
            $partner = Partner::where('user_id', $user_id)->first();
            if (empty($partner)) {
                return self::response(self::CONTENT_IS_EMPTY);
            }
            return self::response(self::SUCCESS, $partner[0]->id);
        }catch (\Exception $e){
            return self::response(self::SYSTEM_ERROR);
        }
    }

    /**
     * 通过loginSession返回用户ID
     * @param $loginSession
     * @return mixed 合作者ID
     */
    public static function getUserIdByLoginSession($loginSession){
        try {
            $wx_app_openid = Redis::get($loginSession);
            $user = Users::where('wx_app_openid', $wx_app_openid)->first();
            if (empty($user)) {
                return self::response(self::CONTENT_IS_EMPTY);
            }
            return self::response(self::SUCCESS, $user->id);
        }catch (\Exception $e){
            return self::response(self::SYSTEM_ERROR);
        }
    }

    /**
     * 发送小程序系统通知
     * @param $data
     * @return mixed
     */
    public static function sendSystemNotify($data, $access_token){
//        try {
            $url = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=" . $access_token;
            $ch = curl_init($url);
            $data_string = json_encode($data);
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_HTTPHEADER, array(
                    'Content-Type: application/json',
                    'Content-Length: ' . strlen($data_string))
            );
            $json_data = json_decode(curl_exec($ch));
            errorLog(objectToArray($json_data));
            if ($json_data->errcode) {
                return self::response(self::SYSTEM_NOTIFY_SEND_FAILD);
            }
            return self::response(self::SUCCESS);
//        }catch (\Exception $e){
//            return self::response(self::SYSTEM_ERROR);
//        }
    }

    /**
     * 通过loginSession返回用户ID
     * @param $loginSession
     * @return mixed 合作者ID
     */
    public static function getWxAppOpenidByLoginSession($loginSession){
        try {
            $wx_app_openid = Redis::get($loginSession);
            $user = Users::where('wx_app_openid', $wx_app_openid)->get();
            if (empty($user)) {
                return self::response(self::CONTENT_IS_EMPTY);
            }
            return self::response(self::SUCCESS, $user[0]->wx_app_openid);
        }catch (\Exception $e){
            return self::response(self::SYSTEM_ERROR);
        }
    }

    public static function send_sms($mobile, $captcha){
        try {
            // 云片appkey
            $apikey = config('app.yunpian_sms.appkey');
            $text = "【一间咖啡馆】您的验证码是" . $captcha;
            $url = "http://yunpian.com/v1/sms/send.json";
            $encoded_text = urlencode("$text");
            $mobile = urlencode("$mobile");
            $post_string = "apikey=$apikey&text=$encoded_text&mobile=$mobile";
            return self::sock_post($url, $post_string);
        }catch (\Exception $e){
            return self::response(self::SYSTEM_ERROR);
        }
    }

    public static function sock_post($url,$query){
        try {
            $data = "";
            $info = parse_url($url);
            $fp = fsockopen($info["host"], 80, $errno, $errstr, 30);
            if (!$fp) {
                return $data;
            }
            $head = "POST " . $info['path'] . " HTTP/1.0\r\n";
            $head .= "Host: " . $info['host'] . "\r\n";
            $head .= "Referer: http://" . $info['host'] . $info['path'] . "\r\n";
            $head .= "Content-type: application/x-www-form-urlencoded\r\n";
            $head .= "Content-Length: " . strlen(trim($query)) . "\r\n";
            $head .= "\r\n";
            $head .= trim($query);
            $write = fputs($fp, $head);
            $header = "";
            while ($str = trim(fgets($fp, 4096))) {
                $header .= $str;
            }
            while (!feof($fp)) {
                $data .= fgets($fp, 4096);
            }
            return $data;
        }catch (\Exception $e){
            return self::response(self::SYSTEM_ERROR);
        }
    }

    /**
     * 通过用户ID获取合作者ID
     * @param $user_id 用户ID
     * @return mixed
     */
    public static function getPartnerIdByUserId($user_id)
    {
        try {
            $user = Users::where('id', $user_id)->get();
            if (empty($user)) {
                return self::response(self::CONTENT_IS_EMPTY);
            }
            return self::response(self::SUCCESS, $user[0]->partner_id);
        }catch (\Exception $e){
            return self::response(self::SYSTEM_ERROR);
        }
    }

    /**
     * 创建普通的二维码
     * @param $content 二维码内容
     * @param $path 保存的服务器本地路径
     * @param $name 保存名称
     */
    public static function createNormalQrcode($content, $path, $name)
    {
        try {
            // 生成二维码到服务器本地
            $result = QrCode::encoding('UTF-8')->size(300)->generate($content, $path . $name . '.' . 'svg');
            if (!$result) {
                return self::response(self::CREATE_NORMAL_QRCODE_FAILD);
            }
            // 将二维码上传到云存储
            $new_url = uploadImage($path . $name . '.' . 'svg', 'user-qrcode');
            return self::response(self::SUCCESS, $new_url);
        }catch (\Exception $e){
            return self::response(self::SYSTEM_ERROR);
        }
    }

    /**
     * 通过key获取partner_id
     * @param $key 合作者秘钥
     * @return mixed 返回结果
     */
    public static function getPartnerIdByKey($key){
        try {
            $partner = Partner::where('key', $key)->first();
            if (empty($partner)) {
                return self::response(self::CONTENT_IS_EMPTY);
            }
            return self::response(self::SUCCESS, $partner->id);
        }catch (\Exception $e){
            return self::response(self::SYSTEM_ERROR);
        }
    }

    /**
     * 为发送系统通知做准备
     * @param $data
     * @return mixed
     */
    public static function createNotify($data, $access_token)
    {
        // 组装请求数组
        $system_notify_data = [
            'touser' => $data['touser'],
            'template_id' => $data['template_id'],
            'page' => $data['page'],
            'form_id' => $data['form_id'],
            'data' => $data['keyword']
        ];
        $response = self::sendSystemNotify($system_notify_data, $access_token);
        if ($response->code){
            return self::response($response->code);
        }
        return self::response(self::SUCCESS);
    }
}